package dirtywords

import (
	"bufio"
	"github.com/slclub/go-tips"
	"github.com/slclub/sensitive"
	"io"
	"os"
	"sync"
)

var once sync.Once

var wf_object *dirty_words

type dirty_words struct {
	wf  *sensitive.Filter
	sep rune
}

func DirtyWords() *dirty_words {
	if wf_object != nil {
		return wf_object
	}

	wf_object = new(dirty_words)
	wf_object.wf = sensitive.New()
	wf_object.sep = '*'
	// root := wf.GenerateWithFile(path)
	once.Do(func() {
		Loading(wf_object)
	})
	return wf_object
}

func Loading(wf_object *dirty_words) {
	wf_object.LoadWordDict(tips.GetRootPath() + "/conf/sensitive.txt")
	//filter_file := filepath.Join(utils.APP_PATH, "conf/web-json/sensitive_word.json")
	//content, err := ioutil.ReadFile(filter_file)
	//if err != nil {
	//	panic(any(err))
	//}
	//texts := []string{}
	//json.Unmarshal(content, &texts)
	//wf_object.dirty = wf_object.wf.Generate(texts)
	//fmt.Println("loading dirty words:", len(texts))
}

func (this *dirty_words) LoadWordDict(path string) error {
	f, err := os.Open(path)
	if err != nil {
		return err
	}
	defer f.Close()

	return this.Load(f, func(b *[]byte) bool {
		if len([]rune(string(*b))) < 2 {
			return false
		}
		if is_english(*b) {
			return false
		}
		return true
	})
}

// Load common method to add words
func (this *dirty_words) Load(rd io.Reader, ff func(b *[]byte) bool) error {
	buf := bufio.NewReader(rd)
	for {
		line, _, err := buf.ReadLine()
		if err != nil {
			if err != io.EOF {
				return err
			}
			break
		}
		rb := ff(&line)
		if rb == true {
			this.wf.AddWord(string(line))
		}
	}
	return nil
}

// return bool  true:包含屏蔽字, false:不包含屏蔽字
func (this *dirty_words) Contains(text string) bool {
	ok, _ := this.wf.Validate(text) //,  bool true:无屏蔽字，false:包含屏蔽字
	return ok == false
}

func (this *dirty_words) Remove(text string) {
	//this.wf.Remove(text, this.dirty)
}

func (this *dirty_words) Replace(text string) string {
	return this.wf.Replace(text, this.sep)
}

// 两两组合
func (this *dirty_words) ReplaceByTwo(text string) string {
	text = this.Replace(text)
	rlist := []rune(text)
	if len(rlist) <= 1 {
		return text
	}

	//排查两辆组合的字符
	for i, n := 1, len(rlist); i < n; i++ {
		for j := 0; j < i; j++ {
			if rlist[i] == '*' || rlist[j] == '*' {
				continue
			}
			newtext := string([]rune{rlist[j], rlist[i]})
			newtext = this.Replace(newtext)
			nrlist := []rune(newtext)
			rlist[j] = nrlist[0]
			rlist[i] = nrlist[1]
		}
	}
	return string(rlist)
}

// functions

func is_english(s2 []byte) bool {
	var e, s, d, o int
	for i := o; i < len(s2); i++ {
		switch {
		case 64 < s2[i] && s2[i] < 91:
			e += 1
		case 96 < s2[i] && s2[i] < 123:
			e += 1
		case 47 < s2[i] && s2[i] < 58:
			d += 1
		case s2[i] == 32:
			s += 1
		default:
			o += 1
		}
		if o >= 1 {
			return false
		}
	}
	return true
}
